﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using RIDA.Globals;

namespace RIDA.DiagramDesigner
{
    public class Connector : Control
    {
        // drag start point, relative to the DesignerCanvas
        private Point? dragStartPoint = null;

        #region Dependencies Properties
        public Point Position
        {
            get { return (Point)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Position.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(Point), typeof(Connector), new UIPropertyMetadata(new Point()));


        public ConnectorOrientation Orientation
        {
            get { return (ConnectorOrientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(ConnectorOrientation), typeof(Connector), new UIPropertyMetadata(ConnectorOrientation.None));

        public double DesignerItemTop
        {
            get { return (double)GetValue(DesignerItemTopProperty); }
            set { SetValue(DesignerItemTopProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DesignerItemTop.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DesignerItemTopProperty =
            DependencyProperty.Register("DesignerItemTop", typeof(double), typeof(Connector), new UIPropertyMetadata(default(double)));

        public double DesignerItemLeft
        {
            get { return (double)GetValue(DesignerItemLeftProperty); }
            set { SetValue(DesignerItemLeftProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DesignerItemLeft.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DesignerItemLeftProperty =
            DependencyProperty.Register("DesignerItemLeft", typeof(double), typeof(Connector), new UIPropertyMetadata(default(double)));

        public Size DesignerItemSize
        {
            get { return (Size)GetValue(DesignerItemSizeProperty); }
            set { SetValue(DesignerItemSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DesignerItemSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DesignerItemSizeProperty =
            DependencyProperty.Register("DesignerItemSize", typeof(Size), typeof(Connector), new UIPropertyMetadata(new Size()));

        private DesignerItem parentDesignerItem;
        public DesignerItem ParentDesignerItem
        {
            get
            {
                if (parentDesignerItem == null)
                    parentDesignerItem = this.GetParent<DesignerItem>(); //this.DataContext as DesignerItem;

                return parentDesignerItem;
            }
        } 
        #endregion
       
        public Connector()
        {
            // fired when layout changes
            base.LayoutUpdated += new EventHandler(Connector_LayoutUpdated);
        }

       /// <summary>
       /// when the layout changes we update the position property
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void Connector_LayoutUpdated(object sender, EventArgs e)
        {
            DesignerCanvas designer = this.GetParent<DesignerCanvas>();
            if (designer != null)
            {
                //get centre position of this Connector relative to the DesignerCanvas
                this.Position = this.TransformToAncestor(designer).Transform(new Point(this.Width / 2, this.Height / 2));
                this.DesignerItemLeft = DesignerCanvas.GetLeft(this.ParentDesignerItem);
                this.DesignerItemTop = DesignerCanvas.GetTop(this.ParentDesignerItem);
                this.DesignerItemSize = new Size(this.ParentDesignerItem.ActualWidth, this.ParentDesignerItem.ActualHeight);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            DesignerCanvas canvas = this.GetParent<DesignerCanvas>();
            if (canvas != null)
            {
                // position relative to DesignerCanvas
                this.dragStartPoint = new Point?(e.GetPosition(canvas));
                e.Handled = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            // if mouse button is not pressed we have no drag operation, ...
            if (e.LeftButton != MouseButtonState.Pressed)
                this.dragStartPoint = null;

            // but if mouse button is pressed and start point value is set we do have one
            if (this.dragStartPoint.HasValue)
            {
                // create connection adorner 
                DesignerCanvas canvas = this.GetParent<DesignerCanvas>();
                if (canvas != null)
                {
                    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(canvas);
                    if (adornerLayer != null)
                    {
                        ConnectorAdorner adorner = new ConnectorAdorner(canvas, this);
                        if (adorner != null)
                        {
                            adornerLayer.Add(adorner);
                            e.Handled = true;
                        }
                    }
                }
            }
        }

    }

    public enum ConnectorOrientation
    {
        None,
        Left,
        Top,
        Right,
        Bottom
    }
}
